﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Util.Strings
{
    public class StringUtility
    {
        private static readonly char[] IntegerDigits = {
	        '0' , '1' , '2' , '3' , '4' , '5' ,
	        '6' , '7' , '8' , '9' , 'a' , 'b' ,
	        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
	        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
	        'o' , 'p' , 'q' , 'r' , 's' , 't' ,
	        'u' , 'v' , 'w' , 'x' , 'y' , 'z'};

        public static string Reverse(string src)
        {
            IEnumerable<char> chars = src.Reverse();
            return string.Join<char>("", chars);
        }

        public static string ToString(int i, int radix)
        {
            if (radix < 2 || radix > 36)
                radix = 10;

            /* Use the faster version */
            if (radix == 10)
            {
                return i.ToString();
            }

            char[] buf = new char[33];
            bool negative = (i < 0);
            int charPos = 32;

            if (!negative)
            {
                i = -i;
            }

            while (i <= -radix)
            {
                buf[charPos--] = IntegerDigits[-(i % radix)];
                i = i / radix;
            }
            buf[charPos] = IntegerDigits[-i];

            if (negative)
            {
                buf[--charPos] = '-';
            }

            return new String(buf, charPos, (33 - charPos));
        }
        public static string ToString(long i, int radix)
        {
            if (radix < 2 || radix > 36)
                radix = 10;
            if (radix == 10)
                return i.ToString();
            char[] buf = new char[65];
            int charPos = 64;
            bool negative = (i < 0);

            if (!negative)
            {
                i = -i;
            }

            while (i <= -radix)
            {
                buf[charPos--] = IntegerDigits[(int)(-(i % radix))];
                i = i / radix;
            }
            buf[charPos] = IntegerDigits[(int)(-i)];

            if (negative)
            {
                buf[--charPos] = '-';
            }

            return new String(buf, charPos, (65 - charPos));
        }
        public static string HexString(double value)
        {
            if (double.IsInfinity(value))
            {
                return value.ToString();
            }
            StringBuilder answer = new StringBuilder(24);
            if (value < 0.0d)
            {
                answer.Append("-");
            }
            answer.Append("0x");
            value = Math.Abs(value);
            if (value == 0.0)
            {
                answer.Append("0.0p0");
                return answer.ToString();
            }
            bool subnormal = (value < 2.2250738585072014E-308);
            answer.Append(subnormal ? "0." : "1.");
            long signifBits = (BitConverter.DoubleToInt64Bits(value)
                   & 4503599627370495L) | 0x1000000000000000L;
            string signif = Convert.ToString(signifBits, 16).Substring(3, 13);
            answer.Append(signif.Equals("0000000000000") ? // 13 zeros
                              "0" :
                              signif.Replace("0{1,12}$", ""));
            answer.Append("p" + (subnormal ?
              -1022 : (((BitConverter.DoubleToInt64Bits(value) & 9218868437227405312L) >> (53 - 1)) - 1023)));
            return answer.ToString();
        }
        public static string BytesToHex(byte[] bytes)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }

            StringBuilder builder = new StringBuilder("");
            for (int i = 0, length = bytes.Length; i < length; i++)
            {
                builder.Append(bytes[i].ToString("x2"));
            }
            return builder.ToString();
        }
    }
}
